using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

using ProjectMercury;
using ProjectMercury.Emitters;
using ProjectMercury.Modifiers;
using ProjectMercury.Renderers;

namespace ParticleTest
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        GameObject shipCannon;

        int nivel = 1;

        //lista  de missels
        List<GameObject> cannonMissiles = new List<GameObject>();

        List<GameObject> cannonMissiles2 = new List<GameObject>();


        //lista meteoros 
        List<GameObject> Meteors = new List<GameObject>();

        //lista de vetores
        List<Vector2> meteorPositions = new List<Vector2>();

        List<Rectangle> meteorRects = new List<Rectangle>();

        Texture2D Fundo;

        Texture2D meteorTexture;

        BarraEnergia vidaNave;

        int Score = 0;

        GameObject shipCannon2;

        const int maxCannonMissiles = 5;

        public Rectangle viewportRect;

        double GameTime = 0;

        SpriteFont Debug, HUD;

        float BlockSpawnProbability = 0.5f;
        const int BlockFallSpeed = 5;

        float timeProbability = 1f;

        double time = 0;

        // Renderer that draws particles to screen
        Renderer myRenderer;
        // Particle effect object to store the info about particle
        ParticleEffect myEffect;

        #region Tela
        Vector2 fundopos;

        public Vector2 tamanhoTela;

        float velocidadeFundo = 1f;
        #endregion

        Random random = new Random();

        //Criando nossa nave principal
        naveprincipal naveMae;

        KeyboardState previousKeyboradState = Keyboard.GetState();

        #region Construtor
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Create new renderer and set its graphics devide to "this" device
            myRenderer = new SpriteBatchRenderer
            {
                GraphicsDeviceService = graphics
            };
            myEffect = new ParticleEffect();
        }
        #endregion

        #region Initialize
        protected override void Initialize()
        {

            base.Initialize();

            naveMae = new naveprincipal(Content.Load<Texture2D>("Sprites\\Mother"), viewportRect);

            tamanhoTela = new Vector2(graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height);


        }
        #endregion

        #region LoadContent
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // load particle effects
            myEffect = Content.Load<ParticleEffect>(@"EffectLibrary\BasicExplosion");
            myEffect.LoadContent(this.Content);
            myEffect.Initialise();
            myRenderer.LoadContent(Content);

            shipCannon = new GameObject(Content.Load<Texture2D>("Sprites\\shipCannon"));

            // shipCannon2 = new GameObject(Content.Load<Texture2D>("Sprites\\shipCannon"));

            HUD = Content.Load<SpriteFont>("Fonts\\HUD");

            meteorTexture = Content.Load<Texture2D>("Sprites\\Meteorito");

            Debug = Content.Load<SpriteFont>("Fonts\\Score");

            Fundo = Content.Load<Texture2D>("Sprites\\fundo");

            shipCannon2 = new GameObject(Content.Load<Texture2D>("Sprites\\shipCannon"));

            shipCannon2.position = new Vector2(Window.ClientBounds.Width / 2 - shipCannon.sprite.Width / 2 + 110,
               Window.ClientBounds.Height - 100);


            shipCannon.position = new Vector2(Window.ClientBounds.Width / 2 - shipCannon.sprite.Width / 2 - 80,
                Window.ClientBounds.Height - 100);

            //shipCannon2.position = new Vector2(Window.ClientBounds.Width / 2 - shipCannon.sprite.Width / 2  + 100,
            //Window.ClientBounds.Height - 20);

            viewportRect = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width,
                graphics.GraphicsDevice.Viewport.Height);





        }
        #endregion

        #region UnloadContent
        protected override void UnloadContent()
        {
        }
        #endregion

        #region Update
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            vidaNave = new BarraEnergia(naveMae.vidaNave, Content.Load<Texture2D>("Sprites\\HealthBar2"),
                new Vector2(5, 60));

            #region Gerador de posicoes meteoros

            time += gameTime.ElapsedGameTime.TotalSeconds;

            if (random.NextDouble() < BlockSpawnProbability)
            {
                float x = (float)random.NextDouble() *
                    (Window.ClientBounds.Width - meteorTexture.Width);

                if (time > timeProbability)
                {

                    meteorPositions.Add(new Vector2(x, -meteorTexture.Height));

                    time = 0;
                }
            }
            #endregion

            KeyboardState keyboradState = Keyboard.GetState();

            GameTime += gameTime.ElapsedGameTime.TotalSeconds;

            if (keyboradState.IsKeyDown(Keys.Escape))
            {
                this.Exit();
            }

            if (GameTime > 10)
            {
                this.timeProbability = 0.4f;

                nivel = 2;
            }

            #region MovimentoFundo
            if (fundopos.Y >= tamanhoTela.Y)
                fundopos.Y = 0;

            fundopos.Y += velocidadeFundo;

            #endregion

            if (naveMae.vidaNave <= 0)
                this.Exit();

            #region Inputs

            if (keyboradState.IsKeyDown(Keys.Left))
            {
                if (nivel == 2)
                    shipCannon2.rotation = shipCannon.rotation;

                shipCannon.rotation -= 0.05f;

            }



            if (keyboradState.IsKeyDown(Keys.Right))
            {
                if (nivel == 2)
                    shipCannon2.rotation = shipCannon.rotation;

                shipCannon.rotation += 0.05f;
            }

            shipCannon.rotation = MathHelper.Clamp(shipCannon.rotation, -MathHelper.PiOver2 + 0.3f, MathHelper.PiOver2 - 0.3f);

            if (keyboradState.IsKeyDown(Keys.Space) && previousKeyboradState.IsKeyUp(Keys.Space))
            {


                FireCannonMissiles();

            }



            previousKeyboradState = keyboradState;

            #endregion

            // Chamando a funcao que atualiza os misseis
            UpdadeCannonMissiles();

            // Chamando a funcao que atualiza os meteoros
            Updatmeteor();

            // Chamando o update da nave mae
            naveMae.Update(gameTime);

            MouseState ms = Mouse.GetState();
            // Check if mouse left button was presed
            if (ms.LeftButton == ButtonState.Pressed)
            {
                // Add new particle effect to mouse coordinates
                myEffect.Trigger(new Vector2(ms.X, ms.Y));
            }
            // "Deltatime" ie, time since last update call
            float SecondsPassed = (float)gameTime.ElapsedGameTime.TotalSeconds;
            myEffect.Update(SecondsPassed);


            base.Update(gameTime);

        }
        #endregion

        #region Draw
        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);

            //Desenha a NAVE
            naveMae.Draw(spriteBatch);

            vidaNave.Draw(spriteBatch);

            spriteBatch.DrawString(Debug, "Score : " + (int)GameTime, new Vector2(0, 0), Color.White, 0, Vector2.Zero, 1f,
                SpriteEffects.None, 0.1f);

            spriteBatch.DrawString(HUD, "Nave : " + naveMae.vidaNave, new Vector2(0, 20), Color.White,
                0, Vector2.Zero, 1f, SpriteEffects.None, 0.1f);

            //spriteBatch.DrawString(Debug, "" + cannonMissiles, Vector2.Zero, Color.Red);

            //spriteBatch.DrawString(Debug, "" + meteorPositions.Count, new Vector2(0,0), Color.Black);

            //Desenhando os meteoros

            foreach (Vector2 meteorPosition in meteorPositions)
            {

                spriteBatch.Draw(meteorTexture, meteorPosition, null, Color.White, 0,
                    Vector2.Zero, 1.0f, SpriteEffects.None, 0.3f);

                //spriteBatch.DrawString(Debug, "" + meteorPosition, new Vector2(meteorPosition.X, meteorPosition.Y - 50), Color.Black);
            }

            //Desenhando os misseis
            foreach (GameObject Shoot in cannonMissiles)
            {
                //spriteBatch.DrawString(Debug, "" + Shoot.position, new Vector2(0, Shoot.position.Y), Color.Black);
                if (Shoot.alive)
                {
                    spriteBatch.Draw(Shoot.sprite, Shoot.position, null, Color.White,
                        Shoot.rotation, Shoot.center, 1.0f, SpriteEffects.None, 0.4f);
                }
            }

            foreach (GameObject Shoot2 in cannonMissiles2)
            {
                //spriteBatch.DrawString(Debug, "" + Shoot.position, new Vector2(0, Shoot.position.Y), Color.Black);
                if (Shoot2.alive)
                {
                    spriteBatch.Draw(Shoot2.sprite, Shoot2.position, null, Color.White,
                        Shoot2.rotation, Shoot2.center, 1.0f, SpriteEffects.None, 0.4f);
                }
            }




            //spriteBatch.Draw(square, squareRect, Color.Red);

            spriteBatch.Draw(shipCannon.sprite, shipCannon.position, null, Color.White, shipCannon.rotation, shipCannon.center, 1f, SpriteEffects.None, 0.5f);


            if (nivel == 2)
            {

                spriteBatch.Draw(shipCannon.sprite, shipCannon2.position, null, Color.White, shipCannon2.rotation, shipCannon2.center, 1f, SpriteEffects.None, 0.5f);

            }

            #region Movimento do Fundo
            spriteBatch.Draw(Fundo, new Rectangle((int)fundopos.X, (int)fundopos.Y, (int)tamanhoTela.X, (int)tamanhoTela.Y), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0f);
            spriteBatch.Draw(Fundo, new Rectangle((int)fundopos.X, (int)fundopos.Y - (int)tamanhoTela.Y, (int)tamanhoTela.X, (int)tamanhoTela.Y),
            null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0f);
            #endregion



            spriteBatch.End();

            myRenderer.RenderEffect(myEffect);

            base.Draw(gameTime);
        }
        #endregion

        #region  UpdadeCannonMissiles

        public void UpdadeCannonMissiles()
        {

            for (int i = 0; i < cannonMissiles.Count; i++)
            {




                if (cannonMissiles[i].alive)
                {
                    cannonMissiles[i].position += cannonMissiles[i].velocity;

                    cannonMissiles[i].Rect = new Rectangle((int)cannonMissiles[i].position.X,
                        (int)cannonMissiles[i].position.Y, cannonMissiles[i].sprite.Width, cannonMissiles[i].sprite.Height);
                }




                if (!viewportRect.Contains(new Point((int)cannonMissiles[i].position.X, (int)cannonMissiles[i].position.Y)))
                {

                    cannonMissiles.RemoveAt(i);

                    //cannonMissiles[i].alive = false;

                    i--;
                }



            }

            for (int i = 0; i < cannonMissiles2.Count; i++)
            {




                if (cannonMissiles2[i].alive)
                {
                    cannonMissiles2[i].position += cannonMissiles2[i].velocity;

                    cannonMissiles2[i].Rect = new Rectangle((int)cannonMissiles2[i].position.X,
                        (int)cannonMissiles2[i].position.Y, cannonMissiles2[i].sprite.Width, cannonMissiles2[i].sprite.Height);
                }




                if (!viewportRect.Contains(new Point((int)cannonMissiles2[i].position.X, (int)cannonMissiles2[i].position.Y)))
                {

                    cannonMissiles2.RemoveAt(i);

                    //cannonMissiles[i].alive = false;

                    i--;
                }



            }



        }//end UpdateMissiles

        #endregion

        #region FireCannonMissiles

        public void FireCannonMissiles()
        {
            GameObject Shoot = new GameObject(Content.Load<Texture2D>("Sprites\\cannonMissile"));
            GameObject Shoot2 = new GameObject(Content.Load<Texture2D>("Sprites\\cannonMissile"));


            Shoot.alive = true;
            Shoot.position = shipCannon.position;
            Shoot.rotation = shipCannon.rotation;
            Shoot.velocity = new Vector2((float)Math.Sin(shipCannon.rotation),
                (float)-Math.Cos(shipCannon.rotation)) * 10.0f;

            cannonMissiles.Add(Shoot);

            if (nivel == 2)
            {
                Shoot2.alive = true;
                Shoot2.position = shipCannon2.position;
                Shoot2.rotation = shipCannon2.rotation;
                Shoot2.velocity = new Vector2((float)Math.Sin(shipCannon2.rotation),
                    (float)-Math.Cos(shipCannon2.rotation)) * 10.0f;

                cannonMissiles2.Add(Shoot2);
            }

            return;
            //}


        }//end firemissiles

        #endregion

        #region Updatemeteor
        
        public void Updatmeteor()
        {
            // Cria o objeto do tipo meteoro
            GameObject meteor = new GameObject(Content.Load<Texture2D>("Sprites\\Meteorito"));

            for (int i = 0; i < meteorPositions.Count; i++)
            {
                //Animacao do bloco em queda
                //...

                meteorPositions[i] = new Vector2(meteorPositions[i].X,
                                meteorPositions[i].Y + BlockFallSpeed);

                //Obeter o retangulo do meteoro
                meteor.Rect = new Rectangle((int)meteorPositions[i].X, (int)meteorPositions[i].Y,
                   meteorTexture.Width, meteorTexture.Height);


                if (meteorPositions[i].Y > Window.ClientBounds.Height + meteorTexture.Height * 2)
                {
                    meteorPositions.RemoveAt(i);

                    i--;
                }

                //Se colidir com a nave, o meteoro some e a nave perde ponto de vida
                if (meteor.Rect.Intersects(naveMae.retanguloDaNave))
                {
                    //Remove o meteoro da lista
                    meteorPositions.RemoveAt(i);
                    //Diminui a os pontos de vida da nave mar
                    naveMae.vidaNave -= 1;
                    i--;
                }

                //Verificacao de colisao dos meteoros com os misseis
                for (int j = 0; j < cannonMissiles.Count; j++)
                {
                    //Verifica se colidiram
                    if (meteor.Rect.Intersects(cannonMissiles[j].Rect))
                    {
                         //Se colidiram, isso significa que um meteoro foi destruido e o jogador ganha pontos
                        Score += 1;

                        for (int a = 0; a < 60; a++)
                        {
                            myEffect.Trigger(new Vector2(meteor.Rect.X, meteor.Rect.Y));
                        }

                        //Remove o missel da tela
                        cannonMissiles.RemoveAt(j);

                        //Se nao estiver colidindo com a nave mae o meteoro e removido da lista,
                        //esta condicao e feita pois se voce atirar no meteoro e ele estiver 
                        //colidindo ao mesmo tempo com a nave dois comandos manda eles sair da lista, causando um erro
                        if (!meteor.Rect.Intersects(naveMae.retanguloDaNave))
                        {
                            meteorPositions.RemoveAt(i);
                            i--;
                        }
                    }


                }

                for (int o = 0; o < cannonMissiles2.Count; o++)
                {
                    //Verifica se colidiram
                    if (meteor.Rect.Intersects(cannonMissiles2[o].Rect))
                    {
                        //Se colidiram, isso significa que um meteoro foi destruido e o jogador ganha pontos
                        Score += 1;
                        
                        
                        //Remove o missel da tela
                        cannonMissiles2.RemoveAt(o);

                        //Se nao estiver colidindo com a nave mae o meteoro e removido da lista,
                        //esta condicao e feita pois se voce atirar no meteoro e ele estiver 
                        //colidindo ao mesmo tempo com a nave dois comandos manda eles sair da lista, causando um erro
                        if (!meteor.Rect.Intersects(naveMae.retanguloDaNave))
                        {
                            meteorPositions.RemoveAt(i);
                            i--;
                        }
                    }


                }


            }
            //end UpdateMeteors


        #endregion
        }
    }
}
